﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Devonline.Core;
using Devonline.Http;
using Devonline.Identity;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ProjectManagement.Models;

namespace ProjectManagement.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AccountsController : ControllerBase
    {
        private readonly AppSetting _appSetting;
        private readonly ApplicationDbContext _context;
        public AccountsController(ApplicationDbContext context, AppSetting appSetting)
        {
            _context = context;
            _appSetting = appSetting;
        }

        [AllowAnonymous]
        [Display(Name = "登录")]
        [HttpPost("Login")]
        public async Task<IActionResult> Login(UserViewModel userModel)
        {
            try
            {
                var password = userModel.Password.GetHashCode<SHA256>();
                var user = await _context.GetQueryable<User>().FirstOrDefaultAsync(x => x.UserName == userModel.UserName && x.PasswordHash == password);
                if (user != null)
                {
                    if (User.Identity.IsAuthenticated)
                    {
                        return Ok();
                    }

                    var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                    identity.AddClaim(new Claim(ClaimTypes.Sid, user.Id));
                    identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
                    identity.AddClaim(new Claim(ClaimTypes.GivenName, user.Name));
                    identity.AddClaim(new Claim(ClaimTypes.Role, nameof(User)));
                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
                    //Response.Cookies.Append(AppSettings.CACHE_SESSION + user.Id, HttpContext.Session.Id);
                    return Ok();
                }
                else
                {
                    const string badUserNameOrPasswordMessage = "用户名或密码错误";
                    return Unauthorized(badUserNameOrPasswordMessage);
                }
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        /// <summary>
        /// 注销接口
        /// </summary>
        /// <returns></returns>
        [Display(Name = "注销")]
        [HttpGet, HttpPost, Route("logout")]
        public async Task<IActionResult> Logout()
        {
            HttpContext.Session.Clear();
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return Unauthorized();
        }

        /// <summary>
        /// 重置密码接口
        /// </summary>
        /// <returns></returns>
        [Display(Name = "重置密码")]
        [HttpPost("ResetPassword")]
        public async Task<IActionResult> ResetPassword(UserViewModel userModel)
        {
            var password = userModel.OldPassword.GetHashCode<SHA256>();
            var user = await _context.GetQueryable<User>().FirstOrDefaultAsync(x => x.UserName == userModel.UserName && x.PasswordHash == password);
            if (user != null && userModel.Password.IsNotNullOrEmpty() && userModel.Password == userModel.ConfirmPassword)
            {
                user.PasswordHash = userModel.Password.GetHashCode<SHA256>();
                await _context.UpdateToSaveChangeAsync<User, string>(user);
                HttpContext.Session.Clear();
                await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                return Unauthorized();
            }
            else
            {
                const string message = "原始密码输入错误, 请重新输入密码！";
                return BadRequest(message);
            }
        }

        [Display(Name = "数据迁移")]
        [AllowAnonymous, HttpGet("AutoMigration")]
        public async Task<IActionResult> AutoMigrationAsync()
        {
            await _context.AutoMigrationAsync();
            return Ok();
        }

        [Display(Name = "添加默认管理员")]
        [AllowAnonymous, HttpGet("AddAdministrator")]
        public async Task<IActionResult> AddAdministratorAsync()
        {
            if (_context.Users.Any(x => x.UserName == AppSettings.USER_ADMINISTRATOR))
            {
                return BadRequest($"管理员账户 {AppSettings.USER_ADMINISTRATOR} 已存在!");
            }

            var user = new User
            {
                Name = "超级管理员",
                UserName = AppSettings.USER_ADMINISTRATOR,
                PasswordHash = _appSetting.DefaultPassword.GetHashCode<SHA256>(),
                Alias = "管理员"
            };

            user.Create();
            user.Update();
            _context.Add(user);
            await _context.SaveChangesAsync();
            return Ok();
        }
    }
}
